using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace STD.Shared.Domain.ValueObjects;

/// <summary>
/// 邮箱值对象
/// </summary>
public class Email : IEquatable<Email>
{
    /// <summary>
    /// 邮箱地址
    /// </summary>
    public string Value { get; }
    
    private Email(string value)
    {
        Value = value;
    }
    
    /// <summary>
    /// 创建邮箱实例
    /// </summary>
    /// <param name="email">邮箱地址</param>
    /// <returns>邮箱实例</returns>
    public static Email Create(string email)
    {
        if (string.IsNullOrWhiteSpace(email))
            throw new ArgumentException("邮箱地址不能为空", nameof(email));
        
        if (!IsValidEmail(email))
            throw new ArgumentException("邮箱地址格式不正确", nameof(email));
        
        return new Email(email.ToLowerInvariant());
    }
    
    /// <summary>
    /// 验证邮箱格式
    /// </summary>
    /// <param name="email">邮箱地址</param>
    /// <returns>是否有效</returns>
    private static bool IsValidEmail(string email)
    {
        try
        {
            var emailAttribute = new EmailAddressAttribute();
            return emailAttribute.IsValid(email);
        }
        catch
        {
            return false;
        }
    }
    
    /// <summary>
    /// 获取域名部分
    /// </summary>
    /// <returns>域名</returns>
    public string GetDomain()
    {
        var parts = Value.Split('@');
        return parts.Length == 2 ? parts[1] : string.Empty;
    }
    
    /// <summary>
    /// 获取用户名部分
    /// </summary>
    /// <returns>用户名</returns>
    public string GetUsername()
    {
        var parts = Value.Split('@');
        return parts.Length == 2 ? parts[0] : string.Empty;
    }
    
    public override string ToString() => Value;
    
    public bool Equals(Email? other)
    {
        if (other is null) return false;
        if (ReferenceEquals(this, other)) return true;
        return Value == other.Value;
    }
    
    public override bool Equals(object? obj)
    {
        return Equals(obj as Email);
    }
    
    public override int GetHashCode()
    {
        return Value.GetHashCode();
    }
    
    public static bool operator ==(Email? left, Email? right)
    {
        return Equals(left, right);
    }
    
    public static bool operator !=(Email? left, Email? right)
    {
        return !Equals(left, right);
    }
    
    public static implicit operator string(Email email) => email.Value;
} 